const re1 = /<(\w+)\s*([^>]*)>([^<]*)<\/\1>/gm;
const re2 = /<(\w+)\s*([^(/>)]*)\/>/gm;
const nodesMap = new Map();

const instruct = ['v-if'];

class VNode {
    constructor(tag, attr, children, parent, childrenTemplate) {
        this.tag = tag;
        this.attr = attr;
        this.hidden = false;
        this.children = children;
        this.parent = parent;
        this.childrenTemplate = childrenTemplate;
        this.uuid = getUuid();
    }
    isHidden(state) {
        this.hidden = state;
    }
}

const getUuid = () => {
    return Math.random() * 10000000000 +
        Math.random() * 100000 +
        Date.now().toString(32);
}

/** 解析模板 */
function parseTemplate(tmp) {
    tmp = tmp.replace(/\n/gm, "");
    while (re1.test(tmp) || re2.test(tmp)) {
        tmp = tmp2VNode(tmp, [re1, re2]);
    }
    return tmp;
}
/** 模板转vnode */
function tmp2VNode(tmp, regs) {
    regs.forEach(reg => {
        tmp = tmp.replace(reg, (s0, s1, s2, s3) => {
            let attr = tmp2Attribute(s2);
            let node = new VNode(s1, attr, [], null, reg === re1 ? s3 : '');
            nodesMap.set(node.uuid, node);
            return `(${node.uuid})`;
        });
    });
    return tmp;
}
/** 模板转属性map */
function tmp2Attribute(str) {
    let attr = new Map();
    str = str.trim();
    str.replace(/([\w|-]+)\s*=['"](.*?)['"]/gm, (s0, s1, s2) => {
        attr.set(s1, s2);
        return s0;
    });
    return attr;
}
/** 解析 */
function parseTmp2Node(tmp) {
    const re = /\((.*?)\)/g;
    let nodes = [],
        rootStr = tmp.trim();
    [...rootStr.matchAll(re)].forEach(uuidRegResult => {
        let node = nodesMap.get(uuidRegResult[1]);
        if (node.childrenTemplate != '') {
            node.children = parseTmp2Node(node.childrenTemplate);
        };
        nodes.push(node);

    });
    return nodes;
}

/** 创建dom */
function parseNode2Dom(nodeList, data) {
    let fragment = document.createDocumentFragment();
    for (let i = 0; i < nodeList.length; i++) {
        appendElement(fragment, createElement(nodeList[i], data));
    }
    return fragment;
}

/**
 * 创建元素
 */
function createElement(node, data) {
    // 处理指令
    instruct.map(key => {
        if (node.attr.get(key)) {
            node = dealImstruct(node, key, data);
        }
    });

    // 当为隐藏属性时，直接返回
    if (node.hidden) {
        console.log('在俩米娜');
        return;
    };

    // 生成元素
    let el = document.createElement(node.tag);

    // 添加属性
    for (let [key, val] of node.attr) {
        if (!instruct.includes(key)) {
            // 
            // break;
            el.setAttribute(key, templateStringReplceVal(val, data));
        }
    }

    // 插入内容
    if (node.children.length === 0) {
        node.childrenTemplate != '' ? el.innerHTML = templateStringReplceVal(node.childrenTemplate, data) : '';
        // 处理子节点
    } else {
        node.children.map(item => {
            appendElement(el, createElement(item, data))
        });
    }

    return el;
}

/** 插入元素 */
function appendElement(parent, element) {
    element ? parent.appendChild(element) : '';
}

/** 处理指令 */
function dealImstruct(node, key, data) {
    return {
        ['v-if']() {
            if (!strReplaceValue(node.attr.get(key), data)) {
                node.isHidden(true);
            };
            return node;
        }
    } [key]();
}

/** 解析html模板字符串 */
function templateStringReplceVal(str, globalData, localData = null) {
    return str.replace(/{{(.*?)}}/g, (s0, s1) => strReplaceValue(s1, localData || globalData));
}

/** 从字符串换取值 */
function strReplaceValue(str, data) {
    let wayArr = str.split(".");
    let val = data;
    wayArr.forEach(key => {
        val = val[key]
    });
    return val;
}


/** 渲染 */
function render(tmp, data) {
    let uuidTemplate = parseTemplate(tmp);
    let nodeList = parseTmp2Node(uuidTemplate);
    let dom = parseNode2Dom(nodeList, data);
    document.body.appendChild(dom);
}






let tmpl = `<div class="newslist">
<div class="img" v-if="info.showImage"><img src="{{image}}"/></div>
<div class="date" v-if="info.showDate">车市： {{info.name}} {{image}}</div>
<div class="img">{{info.name}}</div>
</div>`;

render(tmpl, {
    image: "./basicprofile.jpeg",
    info: {
        showImage: true,
        showDate: false,
        name: "aaa"
    }
})